package com.yanqu.road.utils.string;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import org.apache.commons.logging.LogFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;

/**
 * 字符串辅助类
 */
public class StringUtils {

	public static final String SEPARATOR = "@#$";
	//使用分隔符时需要转义
	public static final String SPLIT_SEPARATOR = "@#\\$";

	private static final Set<Character.UnicodeBlock> mJapaneseUnicodeBlocks = new HashSet<Character.UnicodeBlock>() {{
		add(Character.UnicodeBlock.HIRAGANA);
		add(Character.UnicodeBlock.KATAKANA);
		add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS);
	}};

	private static final Logger log = LogManager.getLogger(StringUtils.class.getName());

	public static String clearHeadAndTailEmpty(String str) {
		str = str.trim();
		while (str.startsWith("　")) {//这里判断是不是全角空格
			str = str.substring(1, str.length()).trim();
		}
		while (str.endsWith("　")) {
			str = str.substring(0, str.length() - 1).trim();
		}
		str = str.replaceAll("\n", " ");
		return str;
	}

	/**
	 * list加分隔符转string
	 */
	public static String listToString(List list, char separator) {
		if(null == list){
			return "";
		}
		int length = list.size();
		if (0 == length) {
			return "";
		}

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < length; i++) {
			sb.append(list.get(i)).append(separator);
		}
		if (sb.toString().length() == 0) {
			return "";
		}
		return sb.toString().substring(0, sb.toString().length() - 1);
	}

	/**
	 * list加分隔符转string
	 */
	public static String listToString(List list, String separator) {
		if(null == list){
			return "";
		}
		int length = list.size();
		if (0 == length) {
			return "";
		}

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < length; i++) {
			sb.append(list.get(i)).append(separator);
		}
		if (sb.toString().length() == 0) {
			return "";
		}
		return sb.toString().substring(0, sb.toString().length() - separator.length());
	}

	public static List<BigInteger> stringToBigIntegerList(String srcStr, String separator) {
		String[] strArr = srcStr.split(separator);
		if (strArr.length == 1 && isNullOrEmpty(strArr[0])) {
			return new ArrayList<>();
		}
		List<BigInteger> dataList = new ArrayList<>();
		for (String str : strArr){
			if (!isNullOrEmpty(str)) {
				dataList.add(new BigInteger(str));
			}
		}
		return dataList;
	}

	public static List<Long> stringToLongList(String srcStr, String separator) {
		String[] strArr = srcStr.split(separator);
		if (strArr.length == 1 && isNullOrEmpty(strArr[0])) {
			return new ArrayList<>();
		}
		List<Long> dataList = new ArrayList<>();
		for (String str : strArr){
			if (!isNullOrEmpty(str)) {
				dataList.add(string2longSafe(str, 0));
			}
		}
		return dataList;
	}

	public static List<Integer> stringToIntegerList(String srcStr, String separator) {
		String[] strArr = srcStr.split(separator);
		if (strArr.length == 1 && isNullOrEmpty(strArr[0])) {
			return new ArrayList<>();
		}
		List<Integer> dataList = new ArrayList<>();
		for (String str : strArr){
			if (!isNullOrEmpty(str)) {
				dataList.add(string2intSafe(str, 0));
			}
		}
		return dataList;
	}

	public static LinkedList<Integer> stringToIntegerLinkedListNoZero(String srcStr, String separator) {
		String[] strArr = srcStr.split(separator);
		if (strArr.length == 1 && isNullOrEmpty(strArr[0])) {
			return new LinkedList<>();
		}
		LinkedList<Integer> dataList = new LinkedList<>();
		for (String str : strArr){
			if (!isNullOrEmpty(str)) {
				int value = string2intSafe(str, 0);
				if(value > 0) {
					dataList.addLast(value);
				}
			}
		}
		return dataList;
	}

	public static List<Integer> stringToIntegerListNoZero(String srcStr, String separator) {
		String[] strArr = srcStr.split(separator);
		if (strArr.length == 1 && isNullOrEmpty(strArr[0])) {
			return new ArrayList<>();
		}
		List<Integer> dataList = new ArrayList<>();
		for (String str : strArr){
			if (!isNullOrEmpty(str)) {
				int value = string2intSafe(str, 0);
				if(value > 0) {
					dataList.add(value);
				}
			}
		}
		return dataList;
	}

	public static List<String> stringToStringList(String srcStr, String separator) {
		String[] strArr = srcStr.split(separator);
		if (strArr.length == 1 && isNullOrEmpty(strArr[0])) {
			return new ArrayList<>();
		}
		List<String> dataList = new ArrayList<>();
		for (String str : strArr){
			if (!isNullOrEmpty(str)) {
				dataList.add(str);
			}
		}

		return dataList;
	}


	/**
	 * 判断字符串是否为空
	 */
	public static boolean isNullOrEmpty(String str) {
		return str == null || str.trim().length() == 0;
	}

	/**
	 * 是否为数字类型(注意负数返回false),空字符串也会返回true!!!!
	 */
	public static boolean isNumber(String str) {
		if (isNullOrEmpty(str)){
			return false;
		}
		return str.matches("\\d*");
	}

	public static int parseInt(String str) {
		if (isNullOrEmpty(str) || !isNumber(str)) {
			return 0;
		}
		return Integer.parseInt(str);
	}

	/**
	 * 获取字符串长度(中文计算两个长度)
	 */
	public static int getStringLen(String str) {
		if (null == str) {
			return 0;
		}
		int len = 0;
//		str = str.trim();
		if (str.length() < 1) {
			return len;
		}
		char[] arr = str.toCharArray();
		int size = arr.length;
		for (int i = 0; i < size; i++) {
			if (isChinese(arr[i]) || isJapaneseChar(arr[i]) || isKoreaChar(arr[i]))
				len += 2;
			else
				len++;
		}
		return len;
	}

	/**
	 * 是否为中文字符
	 */
	private static boolean isChinese(char c) {
		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
		if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
				|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
				|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
				|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
			return true;
		}
		return false;
	}

	/**
	 * 是否为日文
	 * @param c
	 * @return
	 */
	private static boolean isJapaneseChar(char c) {
		if (mJapaneseUnicodeBlocks.contains(Character.UnicodeBlock.of(c))) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 判断是否为韩文
	 * @param c
	 * @return
	 */
	private static boolean isKoreaChar(char c) {
		if (!((c > 0x3130 && c < 0x318F) || (c >= 0xAC00 && c <= 0xD7A3))) {
			return false;
		}
		return true;
	}

	/**
	 * 字符串比较是否一致，空值跟null不一致
	 */
	public static boolean stringEquals(String value1, String value2){
		boolean result = false;
		if(null == value1){
			if(null == value2){
				result = true;
			}else {
				result = false;
			}
		}else {
			result = value1.equals(value2);
		}
		return result;
	}

	/**
	 * 安全转数字
	 */
	public static int string2intSafe(String value, int defaultValue){
		int result;
		try{
			result = Integer.parseInt(value);
		}catch (NumberFormatException e){
			result = defaultValue;
		}
		return result;
	}

	/**
	 * 安全转数字
	 */
	public static long string2longSafe(String value, long defaultValue){
		long result;
		try{
			result = Long.parseLong(value);
		}catch (NumberFormatException e){
			result = defaultValue;
		}
		return result;
	}

	/**
	 * 转换编码
	 */
	public static String autoToUtf8(String str) {
		if (null == str) {
			return null;
		}
		String newStr = new String(str.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
		if (str.length() == newStr.length()) {
			return str;
		}
		return newStr;
	}

	/**
	* 描述：去除空白内容，包括空格、全角空格、特殊空白
	* 作者：zrq
	* 时间：2023/4/12
	* 参数：

	* 返回值：
	**/
	public static String clearBlankSpace(String str){
		if(isNullOrEmpty(str)){
			return "";
		}
		String checkStr = clearHeadAndTailEmpty(str);
		checkStr = checkStr.replaceAll("\u007F", "");
		checkStr = checkStr.replaceAll("ㅤ", "");
		checkStr = checkStr.replaceAll(" ", "");
		checkStr = checkStr.replaceAll("　", "");
		checkStr = checkStr.replaceAll(" ", "");
		return checkStr;
	}

	public static String setToString(Set<Integer> set, String separator) {
		if (set == null || set.size() <= 0) {
			return "";
		}
		StringJoiner joiner = new StringJoiner(separator);
		for (Integer item : set) {
			joiner.add(String.valueOf(item));
		}
		return joiner.toString();
	}

	public static Map<String, Integer> jsonToMap(String json) {
		JSONObject jsonObject = JSONObject.parseObject(json);
		Map<String, Integer> map = new HashMap<>();

		for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
			String key = entry.getKey();
			int value = Integer.parseInt(entry.getValue().toString());
			map.put(key, value);
		}
		return map;
	}

	/**
	 * json to map
	 * @param json
	 * @return
	 */
	public static Map<Integer, String> jsonToMap2(String json) {
		// 使用 TypeReference 转换为 Map<String, String>
		Map<String, String> stringMap = JSON.parseObject(json, new TypeReference<Map<String, String>>() {});
		// 创建一个新的 Map<Integer, String>，用于存放转换后的键值对
		Map<Integer, String> intMap = new HashMap<>();
		for (Map.Entry<String, String> entry : stringMap.entrySet()) {
			intMap.put(Integer.parseInt(entry.getKey()), entry.getValue());
		}
		return intMap;
	}

	/**
	 * map to json
	 * @param map
	 * @return
	 */
	public static String mapToJson(Map<Integer, String> map) {
		// 创建 SerializeConfig 实例
		SerializeConfig config = new SerializeConfig();
		// 使用 ToStringSerializer 来强制将所有 Integer 类型的 key 转换为 String
		config.put(Integer.class, ToStringSerializer.instance);
		// 转换 Map 为 JSON 字符串
		return JSON.toJSONString(map, config);
	}

	/**
	 * string to set
	 * @param str
	 * @return
	 */
	public static Set<Integer> stringToSet(String str, String separator) {
		Set<Integer> set = new HashSet<>();
		// 使用逗号分隔字符串，将其拆分为数组
		String[] strArray = str.split(separator);
		// 将数组转换为 Set
		for (String s : strArray) {
			// 将每个字符串转换为整数并添加到 Set
			set.add(Integer.parseInt(s.trim()));
		}
		return set;
	}

	/**
	 * string to set
	 * @param str
	 * @return
	 */
	public static Set<String> stringToSet2(String str, String separator) {
		Set<String> set = new HashSet<>();
		// 使用逗号分隔字符串，将其拆分为数组
		String[] strArray = str.split(separator);
		// 将数组转换为 Set
		for (String s : strArray) {
			// 将每个字符串转换为整数并添加到 Set
			set.add(s.trim());
		}
		return set;
	}

	/**
	 *  1=3|2=4|5=5|7=6|50=7|51=8 ，
	 *  解析规则为，例子：key为1到1的value=3，key为2到4的value=4，key为5到6的value=5，key为7到49的value=6，依次类推
	 * @param str
	 * @return
	 */
	public static Map<Integer, Integer> parseStringToMap(String str) {
		return parseStringToMap(str, "\\|", "=");
	}

	/**
	 *  1=3|2=4|5=5|7=6|50=7|51=8 ，
	 *  解析规则为，例子：key为1到1的value=3，key为2到4的value=4，key为5到6的value=5，key为7到49的value=6，依次类推
	 * @param str
	 * @return
	 */
	public static Map<Integer, Integer> parseStringToMap(String str, String separator1, String separator2) {
		Map<Integer, Integer> resultMap = new LinkedHashMap<>();
		String[] pairs = str.split(separator1);

		for (int i = 0; i < pairs.length; i++) {
			String[] keyValue = pairs[i].split(separator2);
			int key = Integer.parseInt(keyValue[0]);
			int value = Integer.parseInt(keyValue[1]);

			// 设置第一个键值对的起点
			if (i == 0) {
				for (int k = 1; k <= key; k++) {
					resultMap.put(k, value);
				}
			} else {
				String[] previousPair = pairs[i - 1].split(separator2);
				int previousKey = Integer.parseInt(previousPair[0]);
				int previousValue = Integer.parseInt(previousPair[1]);

				// 填充上一对与当前对之间的空隙
				for (int k = previousKey + 1; k < key; k++) {
					resultMap.put(k, previousValue);
				}
				// 添加当前键值对的值
				for (int k = key; k <= key; k++) {
					resultMap.put(k, value);
				}
			}

			// 处理最后一个键值对到最大键51的情况
			if (i == pairs.length - 1 && key < 51) {
				for (int k = key + 1; k <= 51; k++) {
					resultMap.put(k, value);
				}
			}
		}

		return resultMap;
	}

	public static String format(String pattern, Object ... arguments){
		//待定 要不要给个空
//		if (pattern == null) {
//			return "";
//		}

		String result = pattern;
		try {
			result = MessageFormat.format(pattern, arguments);
		}catch (Exception e){
			log.error("key is error {}",pattern);
			log.error("messageFormat error", e);
		}
		return result;
	}
}
